#!/usr/bin/python
# -*- coding:utf-8 -*-
import math

import pandas as pd

from decimal import Decimal, getcontext, ROUND_HALF_UP
from WellTrajectoryData import WellTrajectoryData
# 设置全局舍入规则为四舍五入，保留两位小数
getcontext().rounding = ROUND_HALF_UP
DECIMAL_PRECISION = Decimal('0.00')  # 两位小数精度

class EstimateEigenvalues:
    def __init__(self, trajectory_data_pair):
        self.trajectory_data_pair = trajectory_data_pair

    def estimate_eigenvalues(self, target_well_depth):

      
        max_row, min_row = self.trajectory_data_pair  # 假设 trajectory_data_pair 是 (maxRow, minRow) 元组
        max_data = WellTrajectoryData(max_row)
        min_data = WellTrajectoryData(min_row)

        if max_data.well_depth == target_well_depth:
            self.calculated_trajectory_data = max_data
        else:
            self.calculated_trajectory_data.well_slope = (min_data.well_slope - max_data.well_slope) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.well_slope
            self.calculated_trajectory_data.azimuth = (min_data.azimuth - max_data.azimuth) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.azimuth
            self.calculated_trajectory_data.vertical_depth = (min_data.vertical_depth - max_data.vertical_depth) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.vertical_depth
            self.calculated_trajectory_data.ns_coordinates = (min_data.ns_coordinates - max_data.ns_coordinates) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.ns_coordinates
            self.calculated_trajectory_data.ew_coordinates = (min_data.ew_coordinates - max_data.ew_coordinates) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.ew_coordinates
            self.calculated_trajectory_data.closed_orientation = (min_data.closed_orientation - max_data.closed_orientation) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.closed_orientation
            self.calculated_trajectory_data.closed_displacement = (min_data.closed_displacement - max_data.closed_displacement) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.closed_displacement
            self.calculated_trajectory_data.eye_displacement = (min_data.eye_displacement - max_data.eye_displacement) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.eye_displacement
            self.calculated_trajectory_data.dogleg_degree = (min_data.dogleg_degree - max_data.dogleg_degree) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.dogleg_degree
            self.calculated_trajectory_data.ordinate = (min_data.ordinate - max_data.ordinate) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.ordinate
            self.calculated_trajectory_data.abscissa = (min_data.abscissa - max_data.abscissa) / (min_data.well_depth - max_data.well_depth) * (target_well_depth - max_data.well_depth) + max_data.abscissa
            self.calculated_trajectory_data.well_depth = target_well_depth

        print(f"estimate_eigenvalues: target_well_depth={target_well_depth}, result={self.calculated_trajectory_data}\n")  # 调试信息
        return self.calculated_trajectory_data



class OtherParameters:
    # 计算最小曲率
    def calculate_min_curvature(self,epsilon):
        try:
            # 当 epsilon 不为 0 时，正常计算
            if epsilon != 0:
                result = 2 / epsilon * math.tan(epsilon / 2)
                return result
            else:
                # 当 epsilon 为 0 时，根据极限值返回 1
                return 1
        except Exception as e:
            # 捕获其他可能的异常，例如 math 域错误等
            print(f"Error in calculation: {e}")
            return 1  # 返回默认值 1

    def calculate_d_theta(self, ns_coord, ew_coord):
        if ns_coord == 0:
            # 如果 ns_coord 为 0，直接返回 PI/2
            return math.pi / 2
        try:
            # 计算反正切值的绝对值
            theta = abs(math.atan(ew_coord / ns_coord))
            return theta
        except Exception as e:
            # 捕获其他可能的异常，例如 math 域错误等
            print(f"Error in calculation: {e}")
            return math.pi / 2  # 返回默认值 PI/2
    def calculate_theta(self, ns_coord, ew_coord):
        if ns_coord > 0 and ew_coord > 0:
            return self.calculate_d_theta(ns_coord, ew_coord)
        elif ns_coord < 0 and ew_coord > 0:
            return math.pi - self.calculate_d_theta(ns_coord, ew_coord)
        elif ns_coord < 0 and ew_coord < 0:
            return math.pi + self.calculate_d_theta(ns_coord, ew_coord)
        else:
            return 2 * math.pi - self.calculate_d_theta(ns_coord, ew_coord)

    # def calculate_theta(self, ns_coord, ew_coord):
    #     if ns_coord == 0:
    #         return math.pi / 2 if ew_coord > 0 else 3 * math.pi / 2
    #
    #     basic_angle = self.calculate_d_theta(ns_coord, ew_coord)
    #     if ns_coord > 0 and ew_coord >= 0:
    #         return basic_angle
    #     elif ns_coord < 0 and ew_coord > 0:
    #         return math.pi - basic_angle
    #     elif ns_coord < 0 and ew_coord <= 0:
    #         return math.pi + basic_angle
    #     else:
    #         return 2 * math.pi - basic_angle
    def calculate_closed_direction(self, theta):
        try:
            # res= theta/math.pi*180
            # return res
            return math.degrees(theta)
        except Exception as e:
            # 捕获其他可能的异常，例如 math 域错误等
            print(f"Error in calculation: {e}")
            return 0
    def calculate_other_parameters(self, cur_prev_data_pair,design_direction=188.00,vertical_base_val=3246136.98,horrizontal_base_val=18550536.42):

        current_data=cur_prev_data_pair[1]
        previous_data=cur_prev_data_pair[0]
        if(current_data.well_depth>0):
            paragraph = current_data.well_depth - previous_data.well_depth
            curv1 = previous_data.well_slope*math.pi/180
            curv2 = current_data.well_slope*math.pi/180
            derection_cur1 = previous_data.azimuth*math.pi/180
            derection_cur2 = current_data.azimuth*math.pi/180
            ε = math.cos(curv2-curv1)-math.sin(curv2)*math.sin(curv1)*(1-math.cos(derection_cur2-derection_cur1))
            min_curvature = self.calculate_min_curvature(math.acos(ε))
            current_data.vertical_depth = previous_data.vertical_depth+paragraph/2*(math.cos(curv1)+math.cos(curv2))*min_curvature
            current_data.ns_coordinates = previous_data.ns_coordinates + paragraph/2*(math.sin(curv1)*math.cos(derection_cur1)+math.sin(curv2)*math.cos(derection_cur2))*min_curvature
            current_data.ew_coordinates = previous_data.ew_coordinates + paragraph/2*(math.sin(curv1)*math.sin(derection_cur1)+math.sin(curv2)*math.sin(derection_cur2))*min_curvature
            cur_theta = self.calculate_theta(current_data.ns_coordinates, current_data.ew_coordinates)
            current_data.closed_orientation = self.calculate_closed_direction(cur_theta)
            current_data.closed_displacement = math.sqrt(current_data.ns_coordinates**2+current_data.ew_coordinates**2)
            current_data.eye_displacement =math.cos(design_direction*math.pi/180-cur_theta) *math.sqrt(current_data.ns_coordinates**2+current_data.ew_coordinates**2)
            current_data.dogleg_degree = math.acos(ε)*180/math.pi*30/paragraph
            current_data.ordinate = vertical_base_val+current_data.ns_coordinates
            current_data.abscissa = horrizontal_base_val+current_data.ew_coordinates
        return current_data

class TrueThickness:
    def trueThickness(self, upper_data, lower_data, inclination_angle, is_inclined):
        """计算真实厚度
        Args:
            upper_data: 上部数据点
            lower_data: 下部数据点
            inclination_angle: 倾角
            is_inclined: 是否上倾
        """
        try:
            if is_inclined:
                return ((lower_data.vertical_depth - upper_data.vertical_depth) + 
                        (lower_data.eye_displacement - upper_data.eye_displacement) * 
                        math.tan(math.radians(inclination_angle))) * math.cos(math.radians(inclination_angle))
            else:
                return ((lower_data.vertical_depth - upper_data.vertical_depth) - 
                        (lower_data.eye_displacement - upper_data.eye_displacement) * 
                        math.tan(math.radians(inclination_angle))) * math.cos(math.radians(inclination_angle))
        except Exception as e:
            print(f"计算真实厚度错误: {str(e)}")
            return 0

class AngularDifference:
    def calculate_angular_difference(self, upper_slope, lower_slope, vertical_thickness, inclination_angle, is_inclined):
        if is_inclined:
            sin_value = math.sin(math.radians(((90 + inclination_angle) - (upper_slope + lower_slope) / 2)))
            oblique_depth = vertical_thickness / sin_value
            dogleg_degree = 30 * (lower_slope - upper_slope) / oblique_depth
            eye_displacement = math.cos(math.radians(abs(90 - (upper_slope + lower_slope) / 2))) * oblique_depth
            return oblique_depth, dogleg_degree, eye_displacement
        else:
            sin_value = math.sin(math.radians(((90 - inclination_angle) - (upper_slope + lower_slope) / 2)))
            oblique_depth = vertical_thickness / sin_value
            dogleg_degree = 30 * (lower_slope - upper_slope) / oblique_depth
            eye_displacement = math.cos(math.radians(abs(90 - (upper_slope + lower_slope) / 2))) * oblique_depth
            return oblique_depth, dogleg_degree, eye_displacement

class PointAPrediction:
    def predict_point_a(self, true_thickness, inclination_angle, vertical_depth, planar_distance, is_inclined):
        if is_inclined:
            return (vertical_depth + (true_thickness / math.cos(math.radians(inclination_angle))) - (planar_distance * math.tan(math.radians(inclination_angle))))
        else:
            return (vertical_depth + (true_thickness / math.cos(math.radians(inclination_angle))) + (planar_distance * math.tan(math.radians(inclination_angle))))

class TrueInclination:
    def trueInclination(self, vertical_depth, displacement, inclination_angle, is_inclined):
        """计算真实倾角
        Args:
            vertical_depth: 垂深
            displacement: 位移
            inclination_angle: 倾角
            is_inclined: 是否上倾
        """
        try:
            if is_inclined:
                return (vertical_depth + displacement * math.tan(math.radians(inclination_angle))) * (math.cos(math.radians(inclination_angle)))
            else:
                return (vertical_depth - displacement * math.tan(math.radians(inclination_angle))) * (math.cos(math.radians(inclination_angle)))
        except Exception as e:
            print(f"计算真实倾角错误: {str(e)}")
            return 0

class WellParameters(WellTrajectoryData):
    def __init__(self, design_direction=188.00):
        super().__init__()
        self.design_direction = design_direction
        
    def calculateParameters(self, current_data, previous_data):
        """计算井眼轨迹参数
        Args:
            current_data: 当前数据点
            previous_data: 前一个数据点
        """
        try:
            if current_data.well_depth <= 0:
                return current_data
                
            # 计算段长
            segment = current_data.well_depth - previous_data.well_depth
            
            # 转换角度为弧度
            curv1 = math.radians(previous_data.well_slope)
            curv2 = math.radians(current_data.well_slope)
            direction1 = math.radians(previous_data.azimuth)
            direction2 = math.radians(current_data.azimuth)
            
            # 计算最小曲率
            epsilon = math.cos(curv2-curv1) - math.sin(curv2)*math.sin(curv1)*(1-math.cos(direction2-direction1))
            min_curvature = 2/math.acos(epsilon) * math.tan(math.acos(epsilon)/2) if epsilon != 1 else 1
            
            # 计算垂深
            current_data.vertical_depth = (previous_data.vertical_depth + 
                                        segment/2 * (math.cos(curv1) + math.cos(curv2)) * min_curvature)
            
            # 计算南北坐标和东西坐标
            current_data.ns_coordinates = (previous_data.ns_coordinates + 
                                        segment/2 * (math.sin(curv1)*math.cos(direction1) + 
                                                   math.sin(curv2)*math.cos(direction2)) * min_curvature)
            current_data.ew_coordinates = (previous_data.ew_coordinates + 
                                        segment/2 * (math.sin(curv1)*math.sin(direction1) + 
                                                   math.sin(curv2)*math.sin(direction2)) * min_curvature)
            
            # 计算闭合方位
            theta = math.atan2(current_data.ew_coordinates, current_data.ns_coordinates)
            current_data.closed_orientation = math.degrees(theta) % 360
            
            # 计算闭合位移和视平位移
            current_data.closed_displacement = math.sqrt(current_data.ns_coordinates**2 + current_data.ew_coordinates**2)
            current_data.eye_displacement = (math.cos(math.radians(self.design_direction) - theta) * 
                                          current_data.closed_displacement)
            
            # 计算狗腿度
            current_data.dogleg_degree = math.degrees(math.acos(epsilon)) * 30 / segment
            
            return current_data
            
        except Exception as e:
            print(f"计算井眼轨迹参数错误: {str(e)}")
            return current_data
